package wiiusej.hardwareControllers;

import java.sql.Timestamp;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Vector;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentLinkedQueue;

import javax.swing.text.html.HTMLDocument.HTMLReader.BlockAction;

import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;

import wiiusej.Wiimote;
import wiiusej.apptest.statistics.AccelerationPaquet;
import wiiusej.apptest.statistics.AccelerationPaquetList;





public class WiimoteSynchronizer implements Runnable{

	private static Logger fileLogger;
	private ConcurrentLinkedQueue<AccelerationPaquetList> synchonizerQueue;

	private HashMap<Long, SynchronizedCell> wiimotePacketPointers = 
		new HashMap<Long, SynchronizedCell>();
	
	private HashMap<Integer, Wiimote> wiimotes;
	private boolean printedOnce = false;
	
	
	
	public WiimoteSynchronizer(ConcurrentLinkedQueue<AccelerationPaquetList> synchonizerQueue,
			HashMap<Integer, Wiimote> wiimotes){
		
		this.synchonizerQueue = synchonizerQueue;
		this.wiimotes = wiimotes;
		
		PropertyConfigurator.configure("log4j.properties");
		this.fileLogger = Logger.getLogger("wiimoteSynchronizer");
		
		createPointers();		
		fileLogger.debug(" INIT SYNC ");
	}

	private void createPointers() {		
		Iterator it = wiimotes.entrySet().iterator();		
		
		while(it.hasNext()){
			Map.Entry entry = (Map.Entry) it.next();
			Wiimote wim = (Wiimote) entry.getValue();
			
			SynchronizedCell aux = new SynchronizedCell(0, null);
			
			wiimotePacketPointers.put(wim.getId(), aux);			
		}		
		fileLogger.info("Created Pointers: " + wiimotePacketPointers);		
	}

	private void movePointer(long wiimoteID){		
		SynchronizedCell aux = wiimotePacketPointers.get(wiimoteID);		
		int pointer = aux.getPointer();
		pointer = pointer+1;
		aux.setPointer(pointer);
		//aux.setTime(nextTime);
		wiimotePacketPointers.put(wiimoteID, aux);		
	}
	
	private void setPointer(long wiimoteID, int where){
		SynchronizedCell aux = wiimotePacketPointers.get(wiimoteID);
		aux.setPointer(where);
		wiimotePacketPointers.put(wiimoteID, aux);
	}
	
	@Override
	public void run() {
	
		while(true){
			
			AccelerationPaquetList take;
			
			while( (take = synchonizerQueue.poll()) == null){
				//wait
			}		
			
			Timestamp now = new Timestamp(System.currentTimeMillis());
							
			if(take.getPackets().size() > (wiimotePacketPointers.get(take.getWiimoteID()).getPointer() + 2)){

				
				fileLogger.info("******************************************************");
				
				fileLogger.info("ListSize: " + take.getPackets().size());
				
				fileLogger.info("BEFORE update");
				fileLogger.info(" PointerPosition: " + wiimotePacketPointers.get(take.getWiimoteID()).getPointer()
						+ " PointerTime: " + wiimotePacketPointers.get(take.getWiimoteID()).getTime());
				

				setPointer(take.getWiimoteID(), take.getPackets().size()-2);
				uploadTimeStamp(take, take.getWiimoteID());
				
				fileLogger.info("AFTER update");
				fileLogger.info(" PointerPosition: " + wiimotePacketPointers.get(take.getWiimoteID()).getPointer()
						+ " PointerTime: " + wiimotePacketPointers.get(take.getWiimoteID()).getTime());
				
				fileLogger.info("******************************************************");
				fileLogger.info("");
			}
			
			if(take.getPackets().size() == wiimotePacketPointers.get(take.getWiimoteID()).getPointer() +2){					
				
				uploadTimeStamp(take, take.getWiimoteID());
			
				fileLogger.info("******************************************************");
				fileLogger.info("WIIMOTE INFO: " + take.getWiimoteID() + " At: " + now);
				fileLogger.info("ListSize: " + take.getPackets().size() + 
						" PointerPosition: " + wiimotePacketPointers.get(take.getWiimoteID()).getPointer()
						+ "PointerTime: " + wiimotePacketPointers.get(take.getWiimoteID()).getTime());
				
				printedOnce = false;
				printResults(take, wiimotePacketPointers.get(take.getWiimoteID()).getPointer());
				movePointer(take.getWiimoteID());					
			}
		}
		
	}

	private void uploadTimeStamp(AccelerationPaquetList take, long wiimoteID) {
		
		Timestamp newTime;
		int index = wiimotePacketPointers.get(take.getWiimoteID()).getPointer(); 
		newTime = take.getPackets().get(index).getTime();		
		
		SynchronizedCell aux = wiimotePacketPointers.get(wiimoteID);
		aux.setTime(newTime);
	}

	private void printResults(AccelerationPaquetList take, int end) {		
		if(!printedOnce){
			String sublist = null;

			fileLogger.info("Printing ElementPosition: " + end);
			int i = 0;
			for(AccelerationPaquet packet : take.getPackets().subList(0, end+1)){
				//fileLogger.info(packet.printTimeStamp());
				fileLogger.info("Index: " + i + packet.printTimeStamp());
				i++;
			}		
				
			fileLogger.info("******************************************************");
			fileLogger.info("");
			printedOnce = true;
		}		
	}
	
	
	
	
	
}
